// 定义模板方法模式相关的 trait 和结构体

// 抽象类 AbstractClass
trait AbstractClass {
    // 模板方法，定义了算法骨架，包含一系列方法调用步骤
    fn template_method(&self) {
        self.base_operation1();
        self.required_operations1();
        self.base_operation2();
        self.hook1();
        self.required_operations2();
        self.base_operation3();
        self.hook2();
    }

    // 基本操作方法，具体子类可以重写或实现
    fn base_operation1(&self) {
        println!("AbstractClass: Base operation 1");
    }

    fn base_operation2(&self) {
        println!("AbstractClass: Base operation 2");
    }

    fn base_operation3(&self) {
        println!("AbstractClass: Base operation 3");
    }

    // 抽象方法，必须由具体子类实现
    fn required_operations1(&self);
    fn required_operations2(&self);

    // 钩子方法，子类可以选择性地重写
    fn hook1(&self) {}
    fn hook2(&self) {}
}

// 具体类 ConcreteClassA
struct ConcreteClassA;

impl AbstractClass for ConcreteClassA {
    fn required_operations1(&self) {
        println!("ConcreteClassA: Implemented operation 1");
    }

    fn required_operations2(&self) {
        println!("ConcreteClassA: Implemented operation 2");
    }
}

// 具体类 ConcreteClassB
struct ConcreteClassB;

impl AbstractClass for ConcreteClassB {
    fn required_operations1(&self) {
        println!("ConcreteClassB: Implemented operation 1");
    }

    fn required_operations2(&self) {
        println!("ConcreteClassB: Implemented operation 2");
    }

    // 重写钩子方法 hook1
    fn hook1(&self) {
        println!("ConcreteClassB: Overridden Hook 1");
    }
}

// 主函数入口
pub fn main() {
    println!("Same client code can work with different subclasses:");

    // 创建 ConcreteClassA 实例并调用模板方法
    let concrete_class_a = ConcreteClassA;
    concrete_class_a.template_method();

    println!("\n");

    // 创建 ConcreteClassB 实例并调用模板方法
    let concrete_class_b = ConcreteClassB;
    concrete_class_b.template_method();
}
